package com.optimatch.model.solver;
import choco.kernel.common.util.iterators.DisposableIntIterator;
import choco.kernel.solver.ContradictionException;
import choco.kernel.solver.constraints.integer.AbstractLargeIntSConstraint;
import choco.kernel.solver.variables.integer.IntDomainVar;


public class Propagator extends AbstractLargeIntSConstraint {
	
	IntDomainVar[][] matchs;
	IntDomainVar[][] home;
	private int n_matchs;
	private int n_equipes;
	
	public Propagator(IntDomainVar[] vars, IntDomainVar[] matchs_, IntDomainVar[] home_, int nbEquipes) {
		super(vars);
		n_equipes = nbEquipes;
		n_matchs = nbEquipes-1;
		matchs = new IntDomainVar[n_equipes][n_matchs];
		home = new IntDomainVar[n_equipes][n_matchs];
		for (int i = 0; i < n_equipes; i++) {
			for (int j = 0; j < n_matchs; j++) {
				matchs[i][j] = matchs_[i*n_matchs+j];
				home[i][j] = home_[i*n_matchs+j];
			}
		}
	}

	/**
	 * varIdx l'indice de la variable dont le domaine a ete modifie
	 * 1) si equipe ji instanciee a k alors equipe ki setVal(j)
	 * pour toute autre equipe on supprime k et j du domaine
	 * 2) teste place ji et ki : si un des deux est instancie alors on instancie l'autre a l'opposé
	 * intersection de 1) et 2)
	 */
	@Override
	public void awakeOnInst(int varIdx) throws ContradictionException {
		// TODO Auto-generated method stub
		int team = 0, day = 0, id = 0;
		if (varIdx < (n_equipes*n_matchs)) id = varIdx;
		else id = varIdx - (n_equipes*n_matchs);
		team = id/(n_equipes-1);
		day  = id%n_matchs;
		//System.out.println("Var ID : "+id+" team "+team+" day "+day);
		if(varIdx<(n_equipes*n_matchs)) { // matchs instanciés
			if(matchs[team][day].isInstantiated()) {
				int adv = matchs[team][day].getVal();
			//	System.out.println("adv "+adv);
				if(!matchs[adv][day].canBeInstantiatedTo(team)) fail();
				matchs[adv][day].setVal(team);
				for (int i = 0; i < n_equipes; i++) {
					if(i!=team && i!=adv) {
						matchs[i][day].remVal(team);
						matchs[i][day].remVal(adv);
						if(matchs[i][day].getDomainSize()==0) fail();
					}
				}
				if(home[team][day].isInstantiated()) {
					home[adv][day].setVal(1-home[team][day].getVal());
				}
				if(home[adv][day].isInstantiated()) {
					home[team][day].setVal(1-home[adv][day].getVal());
				}
			}
		}
		else { //home instancié
			if (home[team][day].isInstantiated()) {
				if(matchs[team][day].isInstantiated()) {
					int adv = matchs[team][day].getVal();
					home[adv][day].setVal(1-home[team][day].getVal());
				}
			}
		}
	}

	@Override
	public void propagate() throws ContradictionException {
		// TODO Auto-generated method stub
		
		//Si on ne peut pas faire rencontrer l'équipe team avec l'équipe adv le jour day,
		//on supprime team du domaine de match[adv][day]
		
		//Boucles trop couteuses...
		
	/*	for (int team = 0; team < n_equipes; team++) {
			for (int day = 0; day < n_matchs; day++) {
				if(!matchs[team][day].isInstantiated()) {
					for (int adv = 0; adv < n_equipes; adv++) {
						if(!matchs[team][day].canBeInstantiatedTo(adv)) {
							matchs[adv][day].remVal(team);
						}
					}
				}
			}
		}*/
	}

}
